package ufmg.maze.aco;

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

import ufmg.maze.Maze;

public class ColoniaFormigas {

	private Maze maze;
	private List<Formiga> formigas;
	
	public static int N_ITERACOES = 20;
	public static double TAXA_EVAPORACAO = 0.9;
	public static double QUANT_FEROMONIO = 0.1;
	
	private Formiga melhor;

	public ColoniaFormigas(Maze maze) {
		this.maze = maze;
		formigas = new ArrayList<Formiga>();
	}
	
	public void criarPopulacao(int numeroFormigas)
	{
		maze.limparVisitantes();
		if(formigas.isEmpty())
		{
			for (int i = 0; i < numeroFormigas; i++) {
				formigas.add(Formiga.criar(maze.getTamanho(), maze));
			}
		}
		else
		{
			for (int i = 0; i < numeroFormigas; i++) {
				formigas.get(i).popular(maze);
				if(formigas.get(i).isChegou() && melhor==null)
				{
					melhor = new Formiga(formigas.get(i));
				}
				if(formigas.get(i).isChegou() && formigas.get(i).getIndiceFinal()<melhor.getIndiceFinal())
				{
					melhor = new Formiga(formigas.get(i));
					
				}
			}
			
		}
	}
	
	public void atualizacaoFeromonio()
	{
		for (int i = 0; i < formigas.size(); i++) {
			double tamanhoCaminho = formigas.get(i).isChegou()? formigas.get(i).getTamanhoCaminho() : 
				formigas.get(i).getTamanhoCaminho() + formigas.get(i).getGenome().length;
			
			for (int j = 0; j < formigas.get(i).getIndiceFinal(); j++) {				
				Point celula = formigas.get(i).getCelulaFeromonio(j);
				double feromonio = QUANT_FEROMONIO / tamanhoCaminho + maze.getFeromonio(celula.y, celula.x);
				
				maze.setFeromonio(celula.y, celula.x, feromonio);
				
			}
			
		}
	}
	
	public void aplicaEvaporacaoFeromonio()
	{
		for(int i=0; i<maze.getLimiteY(); i+=2)
		{
			for(int j=0; j<maze.getLimiteX(); j+=2)
			{
				double feromonio = maze.getFeromonio(i, j) * TAXA_EVAPORACAO;
				maze.setFeromonio(i, j, feromonio);
			}
			
		}
	}

	public void init(int numeroFormigas) 
	{
		maze.criarMatrizFeromonio();	
		int iteracao = 1;
		System.out.println("Iteração "+iteracao);
		while(iteracao<N_ITERACOES)
		{
			criarPopulacao(numeroFormigas);
			atualizacaoFeromonio();
			aplicaEvaporacaoFeromonio();
			iteracao++;
			System.out.println("Iteração "+iteracao);
		}
		if(melhor!=null)
		{
			melhor.print(maze);
		}
		else
		{
			System.out.println("Não foi encontada solução");
		}
				
	}

}

